﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using System.ComponentModel;
using System.Reflection;

using Microsoft.Forums.MicrosoftForumsProvider;
using Microsoft.Forums.SyncService;
using Microsoft.Forums.OfflineStore;
using System.Collections.ObjectModel;
using Microsoft.Forums.ForumsClient.ThreadedView;

namespace Microsoft.Forums.ForumsClient
{
    public class AppDataModel : BaseDataModel
    {  
        /// <summary>
        ///  Synchronization Controller.
        /// </summary>
        public SynchronizationController SyncController
        {
            get;
            set;

        }

        /// <summary>
        ///  Forum Service Provider
        /// </summary>
        public MicrosoftForumsServiceProvider ServiceProvider
        {
            get;
            set;
        }


        /// <summary>
        ///  Network details 
        /// </summary>
        public NetworkConnection Network
        {
            get;
            private set;
        }

        /// <summary>
        ///  Current Theme Index of the app.
        /// </summary>
        public int ThemeIndex
        {
            get;
            set;
        }

        /// <summary>
        ///  Current Logged In user information.
        /// </summary>
        public UserLogonInformation CurrentUser
        {
            get;
            set;
        }

        /// <summary>
        ///  Local Data Store for this client app.
        /// </summary>
        public ForumsOfflineStore LocalDataStore
        {
            get
            {
                return new ForumsOfflineStore(DatabaseConnectionString);
            }
        }
      
      
        /// <summary>
        ///  Current user Subscribed Forums.
        /// </summary>
        public SubscribedForumsCollection SubscribedForums
        {
            get;
            set;
        }

        /// <summary>
        ///  Connection string to the local store in use.
        /// </summary>
        public string DatabaseConnectionString
        {
            get
            {
               return string.Format("enlist=false;Data Source={0}", Properties.Settings.Default.CurrentDatabaseFileName);
            }
        }

        /// <summary>
        ///  Holds all the application level data
        /// </summary>
        /// <param name="srvcProvider">Service Provider that is used to fetch the data</param>
        public AppDataModel(MicrosoftForumsServiceProvider srvcProvider)
        {
            LoadAppSettings();

            DatabaseUtilities.CreateDatabaseIfDoesNotExist(DatabaseConnectionString);

            ServiceProvider = srvcProvider;

            // If the DefaultSyncBatchSize value is greater than 0 then use that 
            // batch size to download from the server or else leave it with the 
            // default value set by the MicrosoftForumsServiceProvider constructor
            if (Properties.Settings.Default.DefaultSyncBatchSize > 0)
            {
                ServiceProvider.BatchSize = Properties.Settings.Default.DefaultSyncBatchSize;
            }

            CurrentUser = new UserLogonInformation();
            Network = new NetworkConnection();
           
            SetupSync();

            SubscribedForums = new SubscribedForumsCollection();
        }

        /// <summary>
        ///  Clears and Updates the collection with data from the Database.
        ///  We might have to move subscribedforums into a view model later
        /// </summary>
        public void RefreshSubscribedForums()
        {
            
            using (ForumsOfflineStore store = new ForumsOfflineStore(DatabaseConnectionString))
            {
                foreach (var f in store.Forums)
                {
                    /// Add the forum only if it's not already in our subscribed forums list.
                    if (SubscribedForums[f.Id] == null)
                    {
                        var container = new ForumContainer(f, DatabaseConnectionString);
                        SubscribedForums.Add(container);
                        container.PopulateRootPosts();
                        container.RefreshPostCounts();
                    }
                }
            }
        }

        /// <summary>
        ///  Setup Service Provider.
        /// </summary>
        private void SetupSync()
        {
            SyncController = new SynchronizationController(
                DatabaseConnectionString,
                new List<IForumServiceProvider>() { ServiceProvider },
                Network);

            SyncController.SynchronizeForumCompleted += OnSynchronizeForumComplete;
        }

        /// <summary>
        ///  Update the unread posts count on the forum folders
        /// </summary>
        private void OnSynchronizeForumComplete(object sender, SynchronizeCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                SubscribedForums.Refresh(e.SynchronizeForumSummary.ForumId);
                
                var fc = SubscribedForums[e.SynchronizeForumSummary.ForumId];
                if (fc != null)
                {
                    fc.IsSyncInProgress = false;
                }
            }
        }

  
        /// <summary>
        ///  Load application settings.
        /// </summary>
        private void LoadAppSettings()
        {
            // First time the CurrentDatabaseFileName would be empty.
            if (string.IsNullOrEmpty(Properties.Settings.Default.CurrentDatabaseFileName) == true)
            {
                Properties.Settings.Default.CurrentDatabaseFileName = FindOrCreateLocalAppDataFolder() + Properties.Settings.Default.DefaultDatabaseFileName;
            }
            else
            {
                System.IO.FileInfo fileInfo = new System.IO.FileInfo(Properties.Settings.Default.CurrentDatabaseFileName);

                // Does the file extension needs to be checked ?

                if (fileInfo.Directory.Exists == false)
                {
                    FindOrCreateDataFolder(fileInfo.Directory.Name);
                }                
           }
        }


        /// <summary>
        ///  Get the user local app data folder and format the path string to the App data Folder with the application name and version
        ///  If the folder doesn't exist create it.
        /// </summary>
        /// <returns>Path of the folder</returns>
        private string FindOrCreateLocalAppDataFolder()
        {
            string path = System.Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
            path = path + "\\Microsoft Forums Client\\" + Assembly.GetExecutingAssembly().GetName().Version + "\\";
            return FindOrCreateDataFolder(path);
        }

        /// <summary>
        ///  Create the Data Folder
        /// </summary>
        /// <param name="path">Path of the folder</param>
        /// <returns>path to the folder</returns>
        private string FindOrCreateDataFolder(string path)
        {
            if (string.IsNullOrEmpty(path) == true)
            {
                throw new ArgumentNullException("path");
            }

            if (System.IO.Directory.Exists(path) == false)
            {
                // At present not catching any exception intentionally as there is nothing
                // we can do to handle it.
                System.IO.Directory.CreateDirectory(path);
            }
            return path;
        }
    }
}
